package com.crazymakercircle.netty.echoServer;

import com.crazymakercircle.util.Logger;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * 5.11.2 共享NettyEchoServerHandler处理器
 * create by 尼恩 @ 疯狂创客圈
 **/
@ChannelHandler.Sharable
public class NettyEchoServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 静态实例供其他流水线直接引用
     * NettyEchoServerHandler回显服务器处理器没有保存与任何通道连接相关的数据，
     * 也没有内部的其他数据需要保存, 是一个无状态的handler
     * 可共享的handler也需要加 ChannelHandler.Sharable 注解
     */
    public static final NettyEchoServerHandler INSTANCE = new NettyEchoServerHandler();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 读取从对端输入的数据
        ByteBuf in = (ByteBuf) msg;

        Logger.info("msg type: " + (in.hasArray()?"堆内存":"直接内存"));

        int len = in.readableBytes();
        byte[] arr = new byte[len];
        // 这里用的不是readBytes, 所以ByteBuf的读指针没变化
        in.getBytes(0, arr);
//        in.readByte()
        Logger.info("server received: " + new String(arr, "UTF-8"));

        //写回数据，异步任务
        Logger.info("写回前，msg.refCnt:" + (in.refCnt()));

        // 写回数据这里三个方法都可以
        // 实际上这个Handler是把出入站handler合在一起了, 而且没有继承ChannelOutboundHandlerAdapter, 直接在接收数据阶段就写回了
        // 不过流水线上就这一个handler, 所以问题不大
        ChannelFuture f = ctx.writeAndFlush(msg);
//        ChannelFuture f = ctx.pipeline().writeAndFlush(msg);
//        ChannelFuture f = ctx.channel().pipeline().writeAndFlush(msg);


        f.addListener((ChannelFuture futureListener) -> {
            Logger.info("写回后，msg.refCnt:" + in.refCnt());
        });
//        ctx.fireChannelRead(msg);
    }
}
